/* 
 * florence - Florence is a simple virtual keyboard for Gnome.

 * Copyright (C) 2008, 2009, 2010 François Agrech

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  

*/


#include "ramble.h"
#ifdef ENABLE_RAMBLE

/* Create a ramble structure */
struct ramble *ramble_new()
{
       struct ramble *ramble=g_malloc(sizeof(struct ramble));
       /* initialize some value used for the stroke algorithm */
       ramble->cr = NULL;
       ramble->timeout = 10;
       ramble->max_occurrence = 30;
       ramble->border_threshold = 5;
       return ramble;
}


/* Free the ramble structure */
struct ramble *ramble_free(struct ramble *ramble)
{
  	g_free(ramble);
}


/* Init the ramble path */
void init_rambling(GdkWindow* window, struct key *key, int x, int y, struct status *status, struct ramble* ramble)
{
        /* remove the old timeout for poller and reinitialize an other one */
        if (ramble->timeout_id != -1){
        	g_source_remove(ramble->timeout_id);
        }
        ramble->status = status;
        ramble->timeout_id = g_timeout_add(ramble->timeout, (GSourceFunc) poller_rambling, ramble);

        /* initialize the cairo context */
	if (!ramble->cr){
  		ramble->cr=gdk_cairo_create(window);
  		cairo_set_operator(ramble->cr, CAIRO_OPERATOR_SOURCE);
  		cairo_set_line_cap (ramble->cr, CAIRO_LINE_CAP_ROUND);
  		cairo_set_line_join(ramble->cr, CAIRO_LINE_JOIN_ROUND); 
  		cairo_set_source_rgba (ramble->cr, 1, 0, 0, 1);
  		cairo_set_line_width(ramble->cr, 5);
	}
	cairo_move_to(ramble->cr, x, y);
        
        // the first is good I want take anyway this letter, at the first movement will be printed
        ramble->occurrence = ramble->max_occurrence-1;
        ramble->xoldpos = x;
        ramble->yoldpos = y;	
        ramble->key = key;
        ramble->old_key = key;
        status_focus_set(ramble->status, key);
        status_pressed_set(ramble->status, key);
        /* switch off the key */
	status_focus_set(ramble->status, NULL);
}


/* Draw ramble path */
gboolean draw_rambling(int x, int y, struct ramble* ramble)
{
    	cairo_line_to(ramble->cr, x, y);
    	cairo_stroke(ramble->cr);
    	cairo_move_to(ramble->cr, x, y);
}


/* end rambling path */
gboolean end_rambling (struct ramble* ramble)
{
        if (ramble->timeout_id != -1){
        	g_source_remove(ramble->timeout_id);
                ramble->timeout_id = -1;
        }

	if (ramble->cr){       
  		cairo_destroy(ramble->cr);
  		ramble->cr=NULL;
	}
        /* switch off the key */
	status_focus_set(ramble->status, NULL);
	return FALSE;
}


/* This handle the letter border if you exit and reenter a new letter is taken */
gboolean letter_border_rambling(int x, int y, struct status *status,  struct key *key, struct ramble* ramble)
{
        ramble->xoldpos = x;
        ramble->xoldpos = y;
        ramble->status = status;
        if ((!(key))||((status_border_is(status, ramble->xoldpos, ramble->xoldpos, ramble->border_threshold)))){
                /* switch off the key */	
        	status_focus_set(status, NULL);
		ramble->occurrence = 0;
		return TRUE;
       	}
        return FALSE;
} 


/* It is called from a timer to update the samplings */
gboolean poller_rambling(gpointer user_data)
{
        gboolean ret = TRUE;
  	struct ramble *ramble=(struct ramble *)user_data;
   
        if  (!(ramble->old_key)){
       		 return ret;
        }

        if (ramble->key!=ramble->old_key){
                 ramble->occurrence = 0;
       		 return ret;
        }

        if (ramble->occurrence==ramble->max_occurrence/2){
                 // this switch off the key in an half thick
                 status_focus_set(ramble->status, NULL);
        }

  	ramble->occurrence= ramble->occurrence + 1;
       	if (ramble->occurrence==ramble->max_occurrence){
                 // simulate the push button
                 status_focus_set(ramble->status, ramble->old_key);
              	 status_pressed_set(ramble->status, ramble->old_key);
                 status_pressed_set(ramble->status, NULL);
        }
        return ret;
}
#endif

